<?php
/**********************
**xml_rpc_server.php
**Date Created: 4/13/2009
**Copyright 2009 Tomorrow Tech Industries
**Contact: RPITomorrowTech@gmail.com
**********************/

/**********
TODO: implement better scheme for error handling
	Maybe exceptions?
**********/

require_once 'private/shared/xml_rpc/xmlrpc.inc';
require_once 'private/shared/xml_rpc/xmlrpcs.inc';
require_once('private/shared/errors.inc');
require_once('private/shared/intellistrip.inc');
require_once('private/intellistrip_server.inc');

/***********
XML-RPC callbacks
These are necessary because we cannot callback directly into an object's function because of the 'this' parameters
So, use our factory method to generate the object and pass off to those after authentication
***********/



function setPortPower($params)
{
	$rc = TT_GENERAL;
	$intellistrip = IntellistripServer::getIntellistrip();
	$error = "";

	if( $params->getNumParams() != 1 )
	{
		$error = "Expected single struct";
		$rc = TT_INVALID_INPUT;
	}
	else
	{
		//Extract parameters
		$struct = $params->getParam(0);

		if( !$struct->structmemexists(XMLRPC__PASSWORD) )
		{
			$error = "Missing password";
			$rc = TT_INVALID_INPUT;
		}
		else
		{
			$password = $struct->structmem(XMLRPC__PASSWORD)->scalarval();

			if( !$struct->structmemexists(XMLRPC__SET_PORT_POWER__PORT_ID) )
			{
				$error = "Missing portId";
				$rc = TT_INVALID_INPUT;
			}
			else
			{
				$portId = $struct->structmem(XMLRPC__SET_PORT_POWER__PORT_ID)->scalarval();	

				if( !$struct->structmemexists(XMLRPC__SET_PORT_POWER__POWER_LEVEL) )
				{
					$error = "Missing powerLevel";
					$rc = TT_INVALID_INPUT;
				}
				else
				{
					$powerLevel = $struct->structmem(XMLRPC__SET_PORT_POWER__POWER_LEVEL)->scalarval();	

					//Check authentication
					if( TT_FAILED($intellistrip->isPasswordCorrect($password)) )
					{
						$error = "Incorrect password";
						$rc = TT_ACCESS;
					}
					else
					{
						//Set the power
						$rc = $intellistrip->setPortPower($portId, $powerLevel);
						$error = "intellistrip last error: " . $intellistrip->getLastError();
					}
				}
			}
		}
	}
		
	// Build our response.
	$struct = array(XMLRPC__RC => new xmlrpcval($rc, 'int'), 
					XMLRPC__ERROR => new xmlrpcval($error, ''));
	return new xmlrpcresp(new xmlrpcval($struct, 'struct'));
}

function getPortPower($params)
{
	$rc = TT_GENERAL;
	$intellistrip = IntellistripServer::getIntellistrip();
	$error = "";

	if( $params->getNumParams() != 1 )
	{
		$error = "Expected single struct";
		$rc = TT_INVALID_INPUT;
	}
	else
	{
		//Extract parameters
		$struct = $params->getParam(0);

		if( !$struct->structmemexists(XMLRPC__PASSWORD) )
		{
			$error = "Missing password";
			$rc = TT_INVALID_INPUT;
		}
		else
		{
			$password = $struct->structmem(XMLRPC__PASSWORD)->scalarval();

			if( !$struct->structmemexists(XMLRPC__GET_PORT_POWER__PORT_ID) )
			{
				$error = "Missing portId";
				$rc = TT_INVALID_INPUT;
			}
			else
			{
				$portId = $struct->structmem(XMLRPC__GET_PORT_POWER__PORT_ID)->scalarval();
				
				$powerLevel = '';
				//Check authentication
				if( TT_FAILED($intellistrip->isPasswordCorrect($password)) )
				{
					$error = "Access denied";
					$rc = TT_ACCESS;
				}
				else
				{
					//Query
					$rc = $intellistrip->getPortPower($portId, $powerLevel);
					$error = "intellistrip last error: " . $intellistrip->getLastError();
				}
			}
		}
	}

	// Build our response.
	$struct = array(XMLRPC__RC => new xmlrpcval($rc, 'int'), 
					XMLRPC__ERROR => new xmlrpcval($error, ''),
					XMLRPC__GET_PORT_POWER__POWER_LEVEL => new xmlrpcval($powerLevel, 'int'));
	return new xmlrpcresp(new xmlrpcval($struct, 'struct'));
}

//Returns information such as serial number
function getIntellistripInformation($params)
{
	$rc = TT_GENERAL;
	$intellistrip = IntellistripServer::getIntellistrip();
	$error = "";

	if( $params->getNumParams() != 1 )
	{
		$error = "Expected single struct";
		$rc = TT_INVALID_INPUT;
	}
	else
	{
		//Extract parameters
		$struct = $params->getParam(0)->scalarval();
		
		$vendorName = '';
		$modelNumber = '';
		$modelVersion = '';
		$serialNumber = '';
		$numberPorts = '';
		$state = '';
						
		//Query
		$rc = $intellistrip->getIntellistripInformation($vendorName,
						$modelNumber,
						$modelVersion,
						$serialNumber,
						$numberPorts,
						$state);
		$error = "intellistrip last error: " . $intellistrip->getLastError();
	}

	// Build our response.
	$struct = array(XMLRPC__RC => new xmlrpcval($rc, 'int'), 
					XMLRPC__ERROR => new xmlrpcval($error, ''),
					XMLRPC__GET_INTELLISTRIP_INFORMATION__VENDOR_NAME => new xmlrpcval($vendorName, ''),
					XMLRPC__GET_INTELLISTRIP_INFORMATION__MODEL_NUMBER => new xmlrpcval($modelNumber, ''),
					XMLRPC__GET_INTELLISTRIP_INFORMATION__MODEL_VERSION => new xmlrpcval($modelVersion, ''),
					XMLRPC__GET_INTELLISTRIP_INFORMATION__SERIAL_NUMBER => new xmlrpcval($serialNumber, ''),
					XMLRPC__GET_INTELLISTRIP_INFORMATION__NUMBER_PORTS => new xmlrpcval($numberPorts, 'int'),
					XMLRPC__GET_INTELLISTRIP_INFORMATION__STATE => new xmlrpcval($state, 'int'));
	return new xmlrpcresp(new xmlrpcval($struct, 'struct'));
}	

//Change the access password
//This function has issues and has been disabled
function changePassword($params)
{
	return TT_UNSUPPORTED;
	$rc = TT_GENERAL;
	$intellistrip = IntellistripServer::getIntellistrip();
	$error = "";

	if( $params->getNumParams() != 1 )
	{
		$error = "Expected single struct";
		$rc = TT_INVALID_INPUT;
	}
	else
	{
		//Extract parameters
		$struct = $params->getParam(0);

		if( !$struct->structmemexists(XMLRPC__PASSWORD) )
		{
			$error = "Missing password";
			$rc = TT_INVALID_INPUT;
		}
		else
		{
			$password = $struct->structmem(XMLRPC__PASSWORD)->scalarval();

			if( !$struct->structmemexists(XMLRPC__CHANGE_PASSWORD__NEW_PASSWORD) )
			{
				$error = "Missing newPassword";
				$rc = TT_INVALID_INPUT;
			}
			else
			{
				$newPassword = $struct->structmem(XMLRPC__CHANGE_PASSWORD__NEW_PASSWORD)->scalarval();
				
				$powerLevel = -1;
				//Check authentication
				if( TT_FAILED($intellistrip->isPasswordCorrect($password)) )
				{
					$error = "Incorrect password";
					$rc = TT_ACCESS;
				}
				else
				{
					//Execute
					$rc = $intellistrip->changePassword($newPassword);
					$error = "Last error: " . $intellistrip->getLastError();
				}
			}
		}
	}

	// Build our response.
	$struct = array(XMLRPC__RC => new xmlrpcval($rc, 'int'), 
					XMLRPC__ERROR => new xmlrpcval($error, ''));
	return new xmlrpcresp(new xmlrpcval($struct, 'struct'));
}

//Register XML-RPC functions (callbacks) to handle requests
function registerServers()
{
	$signature = array(array('struct', 'struct'));
	$server = new xmlrpc_server(array(
								INTELLISTRIP_SERVER_CLASS . '.' . XMLRPC__SET_PORT_POWER =>
									array('function' => 'setPortPower',
										  'signature' => $signature,
										  'docstring' => 'Set port power'),
								INTELLISTRIP_SERVER_CLASS . '.' . XMLRPC__GET_PORT_POWER =>
									array('function' => 'getPortPower',
										  'signature' => $signature,
										  'docstring' => 'Query port power'),
								INTELLISTRIP_SERVER_CLASS . '.' . XMLRPC__GET_INTELLISTRIP_INFORMATION =>
									array('function' => 'getIntellistripInformation',
										  'signature' => $signature,
										  'docstring' => 'Query information about this Intellistrip'),
								INTELLISTRIP_SERVER_CLASS . '.' . XMLRPC__CHANGE_PASSWORD =>
									array('function' => 'changePassword',
										  'signature' => $signature,
										  'docstring' => 'Change access password')
								));
			
	return TT_OK;
}

//Setup callbacks
registerServers();

?>


